//
// Created by Ukua on 2023/9/20.
//

#include "BSP_USB.h"
#include "ringbuffer.h"
uint8_t usb_tx_buffer[BSP_USB_TX_RINGBUFFER_SIZE];//ringbuffer
uint8_t usb_tx_sendbuffer[BSP_USB_TX_RINGBUFFER_SIZE];//发送缓存区
ring_buffer_t usb_tx_ringbuffer;
uint8_t usb_connected=0;

Bus_SubscriberTypeDef *g_bsp_usb_tx;
Bus_TopicHandleTypeDef *g_bsp_usb_rx;

osThreadId BSP_USB_MainLoopTaskHandle;

//USB接收回调
void usbd_cdc_rx_callback(uint8_t *data, uint32_t len){
    INTF_UART_MessageTypeDef message;
    message.data = data;
    message.len = len;
    Bus_Publish(g_bsp_usb_rx,&message);
}
void usbd_cdc_tx_callback(uint8_t *Buf, uint32_t *Len, uint8_t epnum){
  if(ring_buffer_is_empty(&usb_tx_ringbuffer))return;
  size_t len=ring_buffer_num_items(&usb_tx_ringbuffer);
  ring_buffer_dequeue_arr(&usb_tx_ringbuffer,(char*)usb_tx_sendbuffer,len);
  CDC_Transmit_FS(usb_tx_sendbuffer, len);
}
/**
 * @brief CAN标准发送话题回调函数
 * @param *message:消息
 * @param *topic:来源话题
 * @note 该函数会将消息储存在fifo中
 */
void BSP_USB_TX_CallBack(void *message, Bus_TopicHandleTypeDef *topic) {
    INTF_UART_MessageTypeDef *msg = (INTF_UART_MessageTypeDef *) message;
    ring_buffer_queue_arr(&usb_tx_ringbuffer,(char*)msg->data,msg->len);
}

void BSP_USB_MainLoop() {
    while (1) {
        INTF_UART_MessageTypeDef msg;
        //发送消息
        if (!ring_buffer_is_empty(&usb_tx_ringbuffer)) {
          size_t len=ring_buffer_num_items(&usb_tx_ringbuffer);
          ring_buffer_dequeue_arr(&usb_tx_ringbuffer,(char*)usb_tx_sendbuffer,len);
          CDC_Transmit_FS(usb_tx_sendbuffer, len);
        }
        osDelay(1);
    }
}

void BSP_USB_Init() {

    //注册话题
    g_bsp_usb_rx = Bus_TopicRegister(BSP_USB_RX_TOPIC_NAME);

    //订阅话题
    g_bsp_usb_tx = Bus_SubscribeFromName(BSP_USB_TX_TOPIC_NAME, BSP_USB_TX_CallBack);

    //FIFO初始化
    ring_buffer_init(&usb_tx_ringbuffer,(char*)usb_tx_buffer,BSP_USB_TX_RINGBUFFER_SIZE);
    //主循环任务
    osThreadDef(BSP_USB_MainLoop_Task, BSP_USB_MainLoop, osPriorityLow, 0, 512);
    BSP_USB_MainLoopTaskHandle = osThreadCreate(osThread(BSP_USB_MainLoop_Task), NULL);
}



